#ifndef GRAPHICELEMENT_H
#define GRAPHICELEMENT_H

#include <ToolBox/matrix.h>
#include <vector>
#include <string>
#include <math.h>
#include <SDL/SDL.h>

#include <GL/glew.h>

class Vbo;

#include "ToolBox/vectorf.h"
#include "ToolBox/gl/vbo.h"
#include <ToolBox/gl/material.h>

#include <DirectLOL/CollisionDetection/aabb.h>
#include <DirectLOL/CollisionDetection/collision.h>

#include <ToolBox/gl/transformation.h>
#include <ToolBox/physic/physic.h>
#include <DirectLOL/actions/action.h>


enum GObjectType    //  Enum utilisé pour connaitre le type des objets fils de displayable à l'aide d'un simple test
{
    oRect,
    oRectT,
    oMesh
};

/*!
 *  =============================================================================================================
 * 	\class GraphicElement()
 * 	\brief Classe mère abstraite servant de base aux différents éléments affichable de la scene OpenGL
 *  =============================================================================================================
 */

class GraphicElement
{
    public :

    /*****************************************************************************************/
    /*                                  Propriétés                                           */
    /*****************************************************************************************/

        /***********************************************/
        /*              Booleans                       */
        /***********************************************/

        Matrix4 & modelView;    /*!< Référence vers la Matrice de modélisation, indispensable pour pouvoir utiliser les
                                    translation, rotation et homotéthie (scale) */

        Vectorf * scaling;      /*!< Valeur de scaling  */

        static Vectorf colorPicking;    /*!<  Permet de savoir quelle sera la prochaine valeur pour identifier un objet */
        Vectorf pickingColor;           /*!< Couleur utilisé pour identifier l'objet lors de l'étape du picking */

        static void IncrementColorPicking();
        static void DefineColorPicking();

        int picked;             /*! Permet de déterminer si un objet à été selectionné

        Physic * physic;
        bool physicOn;
        int kill;

        GLuint picking;    /*!< Si la valeur est égale à 1, le picking a été défini, sinon 0 */
        GLuint lightOn;    /*!< Booléen utilisé pour savoir si l'objet utilise ou non un material pour l'illumination */

        GLuint state;       /*!< Définit l'état de l'élément, si state = 0, l'objet est détruit  */
        GLuint type;        /*!< Identifie le sous-type de l'objet courant (rectangle, sphère etc ...) */



        SDL_Event * event;      /*!< Références aux événements SDL   */

        std::vector<BoundingShape *> boundingShapes;  /*!< Liste de Bounding Box pouvant être lié à l'objet    */
        std::vector<Action *>actions;             /*!< Références aux actions ayant un lien avec l'objet */

        Vbo * vbo;              /*!< Contient les buffers des vbo */
        Material * material;    /*!< Représente un materiau, valeur spéculaure, diffuse et ambiante de l'objet */

        void UpdatePhysic();  /*!< Lance la fonction gérant la physique */
        void SetLight();      /*!< Activation de l'illumination de l'objet */
        void InitBooleans();

        Vectorf * translation;
        Vectorf * translationT1;

        Vectorf * rotation;

        void AddAcceleration(Vectorf * aAcceleration);
        virtual void ResolvePhysic();

    /*****************************************************************************************/
    /*                                  Constructeurs                                        */
    /*****************************************************************************************/

    /*!
     * 	\fn	GraphicElement(int typeObject)
     * 	\brief	Initialise le type de l'objet dérivé
     *
     * 	\param	int typeObject : type de l'objet : rectangle, rectangle texturé, sprite etc
     */

    GraphicElement(int typeObject);

    /*!
     * 	\fn	GraphicElement(int typeObject, Vectorf translation)
     * 	\brief  Initialise le type de l'objet dérivé ainsi que sa position dans la scène openGL via une translation
     *
     * 	\param	int typeObject : type de l'objet : rectangle, rectangle texturé, sprite
     * 	\param 	Vectorf translation : coordonées pour la translation
     */

    GraphicElement(int,Vectorf translation);

    /*!
     * 	\fn	GraphicElement(int typeObject, Vectorf translation)
     * 	\brief  Initialise le type de l'objet dérivé ainsi que sa position dans la scène openGL (translation)
     *
     * 	\param	int typeObject : type de l'objet : rectangle, rectangle texturé, sprite
     * 	\param 	Vectorf translation : coordonées pour la translation
     */

    GraphicElement(int,Vectorf translation, Vectorf rotation);

    virtual ~GraphicElement();

    /*****************************************************************************************/
    /*                                  Fonctions virtuelles pures                           */
    /*****************************************************************************************/

    /*!
     * 	\fn virtual void Display()=0
     * 	\brief Méthode virtuelle pure utilisé pour afficher les trucs
     */

    virtual void Display()=0;

    /*!
     *  \fn virtual void Picking()=0
     *  \brief Méthode virtuelle pure, utiliser pour afficher l'objet avec une unique couleur dans un espace d'affichage "caché"
     *      permettant ainsi de savoir si on a "cliquer" dessus depuis l'écran
     */

    virtual void Picking()=0;

    /*!
     *  \fn virtual void SetPicking(unsigned char x, unsigned char y , unsigned char z)=0
     *  \brief Définit l'identifiant unique de l'objet, utilisé pour le picking
     */

    virtual void SetPicking(unsigned char x, unsigned char y , unsigned char z)=0;

    virtual void SetPhysic();

};


#endif // GRAPHICELEMENT_H
